package cn.me.alphamq.nameserver.event.spi.listener.service;

import cn.me.alphamq.common.entity.resp.ErrorAccountResp;
import cn.me.alphamq.common.entity.resp.ServiceRegistryResp;
import cn.me.alphamq.common.sync.StopWatch;
import cn.me.alphamq.common.util.NettyUtil;
import cn.me.alphamq.nameserver.cache.Container;
import cn.me.alphamq.common.msg.TcpMsg;
import cn.me.alphamq.common.enumeration.EventCodeEnum;
import cn.me.alphamq.nameserver.event.model.service.RegistryEvent;
import cn.me.alphamq.common.event.Listener;
import cn.me.alphamq.nameserver.store.ServiceInstance;
import cn.me.alphamq.common.store.StopWatchManager;
import cn.me.alphamq.nameserver.util.NameServerUtil;
import com.alibaba.fastjson2.JSON;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 服务（包括 broker、producer、consumer）的注册事件的监听器
 *
 * @author f
 */
public class RegistryListener implements Listener<RegistryEvent> {

    private static final Logger log = LoggerFactory.getLogger(RegistryListener.class);

    /**
     * 停表
     */
    private final StopWatch stopWatch = StopWatchManager.newStopWatch();

    // 在本方法中做安全认证
    @Override
    public void onReceive(RegistryEvent event) throws Exception {
        ChannelHandlerContext ctx = event.getCtx();

        // 如果身份校验不通过，则报错
        if (!NameServerUtil.verifyAuth(event.getUsername(), event.getPassword())) {
            ctx.writeAndFlush(new TcpMsg(EventCodeEnum.ERROR_ACCOUNT_RESP,
                    JSON.toJSONBytes(new ErrorAccountResp(event.getMsgId()))));
            ctx.close();
            throw new IllegalAccessException("incorrect username or password");
        }

        // 给服务实例设置一个唯一的标识
        String ip = event.getIp();
        int port = event.getPort();
        String identification = ip + ":" + port;
        NettyUtil.setCtxId(ctx, identification);

        log.info("service instance [{}] is ready", identification);

        // 注册服务实例
        ServiceInstance serviceInstance = new ServiceInstance(
                ctx,
                ip,
                port,
                event.getServiceInstanceType(),
                event.getAttrs()
        );
        Container.getServiceInstanceManager().put(serviceInstance);

        // 将修改的服务实例发给复制消息队列的管理者
        Container.getReplicationMsgQueueManager().putShiftyServiceInstance(serviceInstance, stopWatch);

        // 给 broker 响应一条消息，表示注册成功
        ctx.writeAndFlush(new TcpMsg(EventCodeEnum.REGISTRY_SUCCESS_RESP,
                JSON.toJSONBytes(new ServiceRegistryResp(event.getMsgId()))));
//        log.info("注册成功"); // TODO DELETE
    }
}
